package org.jeie.main;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.Vector;

import org.jeie.actions.EllipseAction;
import org.jeie.actions.FillAction;
import org.jeie.actions.LineAction;
import org.jeie.actions.PencilAction;
import org.jeie.actions.RectAction;
import org.jeie.gui.panels.ColorPanel;
import org.jeie.gui.panels.FillPanel;
import org.jeie.gui.panels.GUIPanel;
import org.jeie.gui.panels.MainPanel;
import org.jeie.gui.panels.ToolboxPanel;
import org.jeie.gui.panels.ToolboxPanel.Tool;
import org.jeie.util.Util;

//TODO	NAME			DONE
//		LINE			*
//		ELLIPSE			*
//		PENCIL			*
//		RECT			*
//		FILL			*
//		EYEDROPPER		*
//		SPRAY			

//		ZOOM			*
//		RESIZE			
//		SCALE			
//		SAVE / OPEN		
//		
// TODO shift for lines, rect, ellipse

public class Listener implements MouseListener, MouseMotionListener {
	private GUIPanel gui;
	private ToolboxPanel toolbox;

	private Vector<Point> pencilList;
	private Color c;
	private Point firstPoint; // mousePressed
	private Point lastPoint; // current
	private int mouseButton; // mousePressed e.getButton();
	private boolean mouseDown = false;

	public Listener(MainPanel mp, GUIPanel gui, ToolboxPanel toolbox) {
		this.gui = gui;
		this.toolbox = toolbox;
	}

	public void mouseDragged(MouseEvent e) {
		lastPoint = e.getPoint();
		if (toolbox.getTool() == Tool.PENCIL) {
			pencilList.add(gui.canvas.screenToImage(originize(e.getPoint())));
		}
		doEyeDropper(e);
		gui.repaint();
	}

	public void mouseMoved(MouseEvent e) {
		lastPoint = e.getPoint();
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {

	}

	public void mouseExited(MouseEvent e) {

	}

	public void mousePressed(MouseEvent e) {
		mouseDown = true;
		ColorPanel cp = EasyImageEditor.mainPanel.toolbox.cp;
		c = e.getButton() == MouseEvent.BUTTON1 ? cp.getForeground() : cp
				.getBackground();
		firstPoint = e.getPoint();
		mouseButton = e.getButton();

		if (toolbox.getTool() == Tool.PENCIL) {
			pencilList = new Vector<Point>();
			pencilList.add(gui.canvas.screenToImage(originize(e.getPoint())));
			gui.repaint();
		}
	}

	public void mouseReleased(MouseEvent e) {
		mouseDown = false;
		ColorPanel cp = EasyImageEditor.mainPanel.toolbox.cp;
		c = e.getButton() == MouseEvent.BUTTON1 ? cp.getForeground() : cp
				.getBackground();
		if (toolbox.getTool() == Tool.PENCIL) {
			gui.canvas.doAction(new PencilAction(pencilList, c, toolbox.lp
					.getLineSize()));
			gui.repaint();
		}
		if (toolbox.getTool() == Tool.RECT) {
			Point firstPoint_ = gui.canvas.screenToImage(originize(firstPoint));
			Point lastPoint_ = gui.canvas.screenToImage(originize(lastPoint));

			Color fore = cp.getForeground();
			Color back = cp.getBackground();
			if (mouseButton == MouseEvent.BUTTON3) {
				Color temp = fore;
				fore = back;
				back = temp;
			}
			gui.canvas.doAction(new RectAction(firstPoint_, lastPoint_, fore,
					back, toolbox.fp.getType(), toolbox.lp.getLineSize()));
			gui.repaint();
		}
		if (toolbox.getTool() == Tool.ELLIPSE) {
			Point firstPoint_ = gui.canvas.screenToImage(originize(firstPoint));
			Point lastPoint_ = gui.canvas.screenToImage(originize(lastPoint));

			Color fore = cp.getForeground();
			Color back = cp.getBackground();
			if (mouseButton == MouseEvent.BUTTON3) {
				Color temp = fore;
				fore = back;
				back = temp;
			}
			gui.canvas
					.doAction(new EllipseAction(firstPoint_, lastPoint_, fore,
							back, toolbox.fp.getType(), toolbox.lp
									.getLineSize()));
			gui.repaint();
		}
		if (toolbox.getTool() == Tool.LINE) {
			Point firstPoint_ = gui.canvas.screenToImage(originize(firstPoint));
			Point lastPoint_ = gui.canvas.screenToImage(originize(lastPoint));
			gui.canvas.doAction(new LineAction(firstPoint_, lastPoint_, c,
					toolbox.lp.getLineSize()));
			gui.repaint();
		}
		if (e.getButton() == MouseEvent.BUTTON1
				&& toolbox.getTool() == Tool.ZOOM) {
			gui.canvas.zoomIn();
			gui.repaint();
		}
		if (e.getButton() == MouseEvent.BUTTON3
				&& toolbox.getTool() == Tool.ZOOM) {
			gui.canvas.zoomOut();
			gui.repaint();
		}
		doEyeDropper(e);
		if (toolbox.getTool() == Tool.FILL) {
			gui.canvas.doAction(new FillAction(gui.canvas
					.screenToImage(originize(e.getPoint())), c));
			gui.repaint();
		}
	}

	private Point originize(Point p) {
		return new Point(p.x - 10, p.y - 10);
	}

	public void preview(Graphics g2) {
		if(!mouseDown)
			return;
		BufferedImage preview = new BufferedImage(gui.canvas.getWidth()
				/ gui.canvas.getZoom(), gui.canvas.getHeight()
				/ gui.canvas.getZoom(), BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = preview.createGraphics();
		g.setColor(c);
		g.setStroke(new BasicStroke(toolbox.lp.getLineSize(),
				BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
		Point firstPoint_ = null;
		Point lastPoint_ = null;
		if (firstPoint != null && lastPoint != null) {
			firstPoint_ = gui.canvas.screenToImage(originize(firstPoint));
			lastPoint_ = gui.canvas.screenToImage(originize(lastPoint));
		}

		if (toolbox.getTool() == Tool.PENCIL && pencilList != null) {
			if (pencilList.size() == 1) {
				g.fillRect(pencilList.get(0).x, pencilList.get(0).y, 1, 1);
			}
			for (int i = 0; i < pencilList.size(); i++) {
				if (i != pencilList.size() - 1) {
					g.drawLine(pencilList.get(i).x, pencilList.get(i).y,
							pencilList.get(i + 1).x, pencilList.get(i + 1).y);
				}
			}
		}
		if (toolbox.getTool() == Tool.RECT && firstPoint != null
				&& lastPoint != null) {
			FillPanel.Type type = toolbox.fp.getType();
			boolean outline = false;
			boolean fill = false;
			switch (type) {
			case OUTLINE:
				outline = true;
				break;
			case FILL:
				fill = true;
				break;
			case FILL_OUTLINE:
				outline = true;
				fill = true;
				break;
			}

			Color fore = toolbox.cp.getForeground();
			Color back = toolbox.cp.getBackground();
			if (mouseButton == MouseEvent.BUTTON3) {
				Color temp = fore;
				fore = back;
				back = temp;
			}

			if (fill) {
				g.setColor(type == FillPanel.Type.FILL ? fore : back);
				Util.fillGoodRect(g, firstPoint_.x, firstPoint_.y,
						lastPoint_.x, lastPoint_.y);
			}
			if (outline) {
				g.setColor(fore);
				Util.drawGoodRect(g, firstPoint_.x, firstPoint_.y,
						lastPoint_.x, lastPoint_.y);
			}
		}

		if (toolbox.getTool() == Tool.ELLIPSE && firstPoint != null
				&& lastPoint != null) {
			FillPanel.Type type = toolbox.fp.getType();
			boolean outline = false;
			boolean fill = false;
			switch (type) {
			case OUTLINE:
				outline = true;
				break;
			case FILL:
				fill = true;
				break;
			case FILL_OUTLINE:
				outline = true;
				fill = true;
				break;
			}

			Color fore = toolbox.cp.getForeground();
			Color back = toolbox.cp.getBackground();
			if (mouseButton == MouseEvent.BUTTON3) {
				Color temp = fore;
				fore = back;
				back = temp;
			}

			if (fill) {
				g.setColor(type == FillPanel.Type.FILL ? fore : back);
				Util.fillGoodOval(g, firstPoint_.x, firstPoint_.y,
						lastPoint_.x, lastPoint_.y);
			}
			if (outline) {
				g.setColor(fore);
				Util.drawGoodOval(g, firstPoint_.x, firstPoint_.y,
						lastPoint_.x, lastPoint_.y);
			}
		}

		if (toolbox.getTool() == Tool.LINE && firstPoint != null
				&& lastPoint != null) {
			g.drawLine(firstPoint_.x, firstPoint_.y, lastPoint_.x, lastPoint_.y);
		}

		g2.drawImage(
				Canvas.resize(preview, gui.canvas.getWidth(),
						gui.canvas.getHeight()), 10, 10, null);
	}

	// tool functions
	private void doEyeDropper(MouseEvent e) {
		if (e.getButton() == MouseEvent.BUTTON1) {
			if (toolbox.getTool() == Tool.EYEDROPPER) {
				toolbox.cp.setForegroundColor(gui.canvas
						.colorAtPoint(gui.canvas.screenToImage(originize(e
								.getPoint()))));
			}
		}
		if (e.getButton() == MouseEvent.BUTTON3) {
			if (toolbox.getTool() == Tool.EYEDROPPER) {
				toolbox.cp.setBackgroundColor(gui.canvas
						.colorAtPoint(gui.canvas.screenToImage(originize(e
								.getPoint()))));
			}
		}
	}
}
